package com.ruoyi.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import com.ruoyi.common.exception.global.CustomException;
import com.ruoyi.common.log.TaskTrace;
import com.ruoyi.config.AppSecurityProperties;
import com.ruoyi.system.vo.JwtResult;
import com.ruoyi.util.jwt.WxJwtUtil;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
@Slf4j
//@Order(2)
public class WxTokenInterceptor implements HandlerInterceptor {

    @Resource
    private AppSecurityProperties appSecurityProperties;

    @Value("${token.secret}")
    private String secret;

    private final AntPathMatcher matcher = new AntPathMatcher();

    @Override
    @TaskTrace
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        String uri = request.getRequestURI();          // 不含域名，如 /wx/login
        /* 2. 白名单放行（支持通配符） */
        String tenantId = request.getHeader("tenantId");
        try {
            request.setAttribute("tenantId", tenantId);    // 下游可用
        }catch (Exception e){
            throw new CustomException("请求头关键参数不能为空");
        }

        if (appSecurityProperties.getPermitAll().stream()
                .anyMatch(pattern -> matcher.match(pattern, uri))) {
            return true;
        }

        /* 3. 其余都要 token */
        String token = request.getHeader("Authorization");
        if (StrUtil.isBlank(token)) {
            logPrint(uri, token);
            throw new CustomException("请先登录", HttpStatus.HTTP_UNAUTHORIZED);
        }
        try {
            String openid = WxJwtUtil.parse(token, secret);
            request.setAttribute("openid", openid);    // 下游可用
            return true;
        } catch (ExpiredJwtException e){
            log.error("出错 token 过期");
            logPrint(uri, token);
            throw new CustomException("token 已过期", HttpStatus.HTTP_UNAUTHORIZED);
        } catch (Exception e) {
            log.error("出错 token 无效", e);
            logPrint(uri, token);
            throw new CustomException("token 无效", HttpStatus.HTTP_UNAUTHORIZED);
        }
    }

    private void logPrint(String uri, String token){
        if (ObjectUtils.isEmpty(token)){
            log.error("拦截请求: {},token不存在", uri);
            return;
        }
        JwtResult jwtResult = WxJwtUtil.parseSilent(token, secret);
        log.error("拦截请求: {},token异常, 用户openId:{}", uri, jwtResult.getSubject());
    }
}
